﻿namespace Engine.Managers
{
    using Engine.Exception;
    using Engine.Properties;
    using Engine.Serialization;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Web;
    using TransferObjects;

    /// <summary>
    /// YQL Requesting manager
    /// </summary>
    public class YahooServiceRequestor : IYahooServiceRequestor
    {
        #region [Attributes]
        private DataType serializerType = DataType.Json;
        private ISerializer<YahooResponse> serializer;
        #endregion

        #region [Properties]
        public IWebClientAdapter WebClientManager { get; set; }
        #endregion

        #region [Methods]
        /// <summary>
        /// Constructor - iniitialize the serializer used by the manager with Json as datatype
        /// </summary>
        public YahooServiceRequestor()
        {
            this.Initialize(DataType.Json);
        }

        /// <summary>
        /// Initialize data serializer
        /// </summary>
        /// <param name="dataType">Request Stream Datatype</param>
        private void Initialize(DataType dataType)
        {
            this.serializerType = dataType;
            this.serializer = SerializerFactory.Instance.GetSerializer<YahooResponse>(dataType);
        }

        /// <summary>
        /// Execute YQL request
        /// </summary>
        /// <param name="request">YQL request</param>
        /// <returns>Response object</returns>
        public YahooResponse Execute(string request)
        {
            YahooResponse result = new YahooResponse();

            try
            {
                string requestURL = this.BuildRequestURL(
                    Settings.Default.YahooServiceUrlBase,
                    new Dictionary<string, string>() { 
                        { "q", request },
                        { "format", serializerType.ToString().ToLower() },
                        { "env", Settings.Default.YahooServiceEnvBase }
                    }
                );

                string response = this.WebClientManager.DownloadString(requestURL);

                result = this.serializer.Deserialize(response);
                result.QueryString = requestURL;
                result.ResponseString = response;
            }
            catch (WebException ex)
            {
                string errorMessage = ex.Message;

                if (ex.Response != null && ex.Response.GetResponseStream() != null)
                {
                    using (var reader = new StreamReader(ex.Response.GetResponseStream()))
                    {
                        Debug.WriteLine(reader.ReadToEnd());
                    }
                }

                throw new YqlResquestException(errorMessage, ex);
            }

            return result;
        }

        /// <summary>
        /// Build YQL Url
        /// </summary>
        /// <param name="urlBase">Yahoo Service URL Base</param>
        /// <param name="parameters">Url parameters</param>
        /// <returns>Url String</returns>
        private string BuildRequestURL(string urlBase, IDictionary<string, string> parameters)
        {
            StringBuilder paramString = new StringBuilder(string.Empty);

            foreach (KeyValuePair<string, string> kvp in parameters)
            {
                paramString.Append(paramString.Length == 0 ? "?" : "&")
                        .Append(HttpUtility.UrlEncode(kvp.Key))
                        .Append("=")
                        .Append(HttpUtility.UrlEncode(kvp.Value));
            }

            return string.Concat(urlBase, paramString.ToString());
        }
        #endregion
    }
}
